package com.zhuqieli.database_learn.service.impl;

import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.CannedAccessControlList;
import com.aliyun.oss.model.CopyObjectResult;
import com.aliyun.oss.model.GeneratePresignedUrlRequest;
import com.aliyun.oss.model.OSSObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhuqieli.database_learn.config.OSSConfig;
import com.zhuqieli.database_learn.dao.FileTableMapper;
import com.zhuqieli.database_learn.dao.UserTableMapper;
import com.zhuqieli.database_learn.enummeration.ResultEnum;
import com.zhuqieli.database_learn.pojo.FileTable;
import com.zhuqieli.database_learn.pojo.UserTable;
import com.zhuqieli.database_learn.service.FileTableService;
import com.zhuqieli.database_learn.enummeration.Result;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import java.net.URL;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * @author dupr
 * @description 文件服务实现类
 * @date 2023/8/30 19:53:17
 */
@Service
public class FileTableServiceImpl extends ServiceImpl<FileTableMapper, FileTable> implements FileTableService {
    @Autowired
    private OSS ossClient;
    //    @Value("${alibaba.oss.bucketName}")
    @Autowired
    private FileTableMapper fileTableMapper;

    @Autowired
    private UserTableMapper userTableMapper;

    @Autowired
    private OSSConfig ossConfig;

    private String bucketName = "xcfglodon";
    //    @Value("${alibaba.oss.fileUrlPrefix}")
    private String fileUrlPrefix;

    //将文件信息保存到数据库
    @Override
    public void uploadFileTable(List<FileTable> fileTables, Integer userId, String username) {
        for (FileTable fileTable : fileTables) {
            fileTableMapper.insert(fileTable);
        }
    }

    @Override
    public URL downloadUrl(String username, String filename) {
        OSS ossClient = ossConfig.ossClient();
        // 设置URL过期时间，以秒为单位
        long expiration = 300; // 1小时
        // 生成URL
        Date expirationTime = new Date(System.currentTimeMillis() + expiration);
        GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, username + "/" + filename);
        request.setExpiration(expirationTime);
        URL url = ossClient.generatePresignedUrl(request);
        // 关闭OSSClient
        ossClient.shutdown();
        return url;
    }

    @Override
    public URL preViewUrl(String username, String filename) {
        OSS ossClient = ossConfig.ossClient();
        // 设置URL过期时间300秒
        long expiration = 300;
        String[] nameAndSuffix = StringUtils.split(filename, ".");
        // 生成URL
        Date expirationTime = new Date(System.currentTimeMillis() + expiration);
        if (!nameAndSuffix[1].equals("jpg")) {
            return ossClient.generatePresignedUrl(bucketName,username + "/" + filename, expirationTime);
        }
        GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, "thumbnail/"+username + "/" + filename);
        request.setExpiration(expirationTime);
        URL url = ossClient.generatePresignedUrl(request);
        // 关闭OSSClient
        ossClient.shutdown();
        return url;
    }

    //数据库增加文件数据
    public void insertFileTable(FileTable fileTable) {
        save(fileTable);
    }

    //依照雪花id修改文件信息
    @Override
    public void upDateFileTable(FileTable fileTable) {
        UpdateWrapper<FileTable> updateWrapper = new UpdateWrapper();
        UpdateWrapper<FileTable> eq = updateWrapper.eq("snowflake_id", fileTable.getSnowflakeId());
        update(fileTable, eq);
    }

    //通过用户id查找文件
    @Override
    public List<FileTable> selectMyfiles(Integer userId) {
        QueryWrapper<FileTable> queryWrapper = new QueryWrapper();
        queryWrapper.eq("user_id", userId);
        queryWrapper.eq("is_deleted", 0);
        List<FileTable> list = list(queryWrapper);
        return list;
    }

    //通过雪花id设置文件已删除
    public void setFileDeleted(String snowflakeId) {
        UpdateWrapper<FileTable> updateWrapper = new UpdateWrapper();
        updateWrapper.eq("snowflake_id", snowflakeId);
        updateWrapper.set("is_deleted", 1);
        update(updateWrapper);
    }

    //通过雪花id设置文件公开
    public void setFilePublic(String snowflakeId) {
        UpdateWrapper<FileTable> updateWrapper = new UpdateWrapper();
        updateWrapper.eq("snowflake_id", snowflakeId);
        updateWrapper.set("public_statu", 1);
        update(updateWrapper);
    }

    //批量设置文件已删除
    @Override
    public void setFileListDeleted(String snowflakeIds) {
            setFileDeleted(snowflakeIds);
    }

    //批量设置文件公开
    @Override
    public void setFileListPublic(String[] snowflakeIds) {
        Arrays.stream(snowflakeIds).forEach(i -> {
            setFilePublic(i);
        });
    }

    //查看本人已删除文件
    @Override
    public List<FileTable> selectUserRecycle(Integer userId) {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("user_id", userId);
        queryWrapper.eq("is_deleted", 1);
        List<FileTable> list = list(queryWrapper);
        return list;
    }

    @Override
    public void rollbackFileDeleted(String snowflakeId) {
        UpdateWrapper<FileTable> updateWrapper = new UpdateWrapper();
        updateWrapper.eq("snowflake_id", snowflakeId);
        updateWrapper.set("is_deleted", 0);
        update(updateWrapper);
    }

    //查看所有已删除文件（用于定时任务查找需要删除的文件）
    public List<FileTable> selectRecycle() {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("is_deleted", 1);
        List<FileTable> list = list(queryWrapper);
        return list;
    }

    //查看公开的所有文件
    @Override
    public List<FileTable> selectAllPublicFiles(int size, int current) {
        int offset = (current - 1) * size;
        List<FileTable> fileTables = fileTableMapper.selectPublic(offset, size);
        return fileTables;
    }

    @Override
    public Result fileDownload(String account, String fileId) {

        try {
            //String account =(String) request.getAttribute("account");
            //String fileId =(String) request.getAttribute("fileId");
            Integer userId = userTableMapper.findIdByName(account);
            String fileName = fileTableMapper.findFileNameByUserIdAndFileId(userId, fileId);
            String suffix = fileTableMapper.findSuffixByUserIdAndFileId(userId, fileId);

            StringBuilder objectName = new StringBuilder();
            objectName.append(account).append("/").append(fileName).append(".").append(suffix);

            String objectNameStr = objectName.toString();

            StringBuilder sbDownloadFilePath = new StringBuilder("D://222/").append(fileName).append(".").append(suffix);

            String downloadFilePath = sbDownloadFilePath.toString();

            // 配置阿里云 OSS 的访问参数
            String endpoint = "oss-cn-chengdu.aliyuncs.com";
            String accessKeyId = "LTAI5tAsndHEZ6JEPx8T7zVs";
            String accessKeySecret = "t8yN9c6bzsi2e1C5Re25qftM2A6nee";
            String bucketName = "xucfglodon";

            // 创建 OSS 客户端
            OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

            // 执行文件下载
            OSSObject ossObject = ossClient.getObject(bucketName, objectNameStr);
            InputStream inputStream = ossObject.getObjectContent();

            try {
                FileOutputStream outputStream = new FileOutputStream(new File(downloadFilePath));
                byte[] buffer = new byte[1024];
                int bytesRead;
                while ((bytesRead = inputStream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, bytesRead);
                }
                outputStream.close();
                inputStream.close();

                System.out.println("文件下载成功：" + downloadFilePath);
                return Result.success();
            } catch (IOException e) {
                e.printStackTrace();
            }

            // 关闭OSSClient
            ossClient.shutdown();
            return Result.success();

        } catch (OSSException oe) {
            throw new IllegalStateException(oe.getMessage());
        }

    }

    @Override
    public String fileSizeShow(String account, String fileId) {
        Integer userId = userTableMapper.findIdByName(account);
        return fileTableMapper.findFileSizeByUserIdAndFileId(userId, fileId);
    }

    //真实删除oss上文件参数实际为filetable的filename
    @Override
    public void fileDelete(String objectName) {

        // 配置阿里云 OSS 的访问参数
        String endpoint = "oss-cn-chengdu.aliyuncs.com";
        String accessKeyId = "LTAI5tAsndHEZ6JEPx8T7zVs";
        String accessKeySecret = "t8yN9c6bzsi2e1C5Re25qftM2A6nee";
        String bucketName = "xucfglodon";

        // 创建 OSS 客户端
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        try {
            // 删除文件
            ossClient.deleteObject(bucketName, objectName);

            System.out.println("文件删除成功！");
        } catch (Exception e) {
            // 异常处理
            System.err.println("文件删除失败：" + e.getMessage());
        } finally {
            // 关闭 OSS 客户端
            ossClient.shutdown();
        }
    }

    @Override
    public void fileRename(String objectName, String newObjectName) {
        try {
            // 复制对象并将其设置为公共读取权限
            CopyObjectResult result = ossClient.copyObject(bucketName, objectName, bucketName, newObjectName);
            ossClient.setObjectAcl(bucketName, newObjectName, CannedAccessControlList.PublicRead);
            // 删除原始对象
            ossClient.deleteObject(bucketName, objectName);
            System.out.println("Object " + objectName + " was renamed to " + newObjectName + " successfully.");
        } catch (OSSException oe) {
            System.out.println("Error renaming object " + objectName + ": " + oe.getMessage());
        }
    }
}
